<!DOCTYPE html>
<html>
  <head>
    <title>Canvas Ninja</title>
    <style>
      canvas {
        border: 1px solid #000;
      }
    </style>
  </head>
  <body>
    <canvas id="ninjaCanvas" width="200" height="200"></canvas>
    <script>
      const canvas = document.getElementById("ninjaCanvas");
      const ctx = canvas.getContext("2d");

      x = 100;
      y = 100;
      r = 50;
      a = 7;
      b = 20;

      radians = 0;

      headscarfRadians = (-radians - Math.PI / 2 + 2 * Math.PI) % (2 * Math.PI);

      subX = Math.cos(radians) * 1.5;
      subY = Math.sin(radians) * 1.5;

      ctx.beginPath();
      ctx.save(); // 保存当前状态
      ctx.translate(x, y); // 将原点移动到旋转中心
      ctx.rotate((-7 * Math.PI) / 180 + headscarfRadians); // 逆时针旋转30度（弧度制）
      ctx.translate(-x, -y);
      const k = 0.5522848; // 贝塞尔曲线控制点系数
      const ox = a * k; // 水平控制点偏移量
      const oy = b * k; // 垂直控制点偏移量

      ctx.moveTo(x - a, y - r);

      // 绘制4段贝塞尔曲线组成椭圆
      ctx.bezierCurveTo(x - a, y - r - oy, x - ox, y - r - b, x, y - r - b);
      ctx.bezierCurveTo(x + ox, y - r - b, x + a, y - r - oy, x + a, y - r);
      ctx.bezierCurveTo(x + a, y - r + oy, x + ox, y - r + b, x, y - r + b);
      ctx.bezierCurveTo(x - ox, y - r + b, x - a, y - r + oy, x - a, y - r);
      ctx.fillStyle = "black";
      ctx.fill();
      ctx.restore(); // 恢复状态

      ctx.beginPath();

      ctx.save(); // 保存当前状态
      ctx.translate(x, y); // 将原点移动到旋转中心
      ctx.rotate((7 * Math.PI) / 180 + headscarfRadians); // 逆时针旋转30度（弧度制）
      ctx.translate(-x, -y);

      ctx.moveTo(x - a, y - r);

      // 绘制4段贝塞尔曲线组成椭圆
      ctx.bezierCurveTo(x - a, y - r - oy, x - ox, y - r - b, x, y - r - b);
      ctx.bezierCurveTo(x + ox, y - r - b, x + a, y - r - oy, x + a, y - r);
      ctx.bezierCurveTo(x + a, y - r + oy, x + ox, y - r + b, x, y - r + b);
      ctx.bezierCurveTo(x - ox, y - r + b, x - a, y - r + oy, x - a, y - r);
      ctx.fillStyle = "black";
      ctx.fill();
      ctx.restore(); // 恢复状态

      //   绘制圆形头部
      ctx.beginPath();
      ctx.arc(x, y, r, 0, Math.PI * 2);
      ctx.fillStyle = "black";
      ctx.fill();

      ctx.beginPath();
      ctx.rect(x - r / 2, y - r / 5, r, (2 * r) / 5); // 参数同fillRect
      ctx.fillStyle = "#f4ea2a";
      ctx.fill();

      ctx.beginPath();
      ctx.arc(x - r / 2, y, r / 5, Math.PI / 2, (3 * Math.PI) / 2);
      ctx.fillStyle = "#f4ea2a";
      ctx.fill();

      ctx.beginPath();
      ctx.arc(x + r / 2, y, r / 5, -Math.PI / 2, Math.PI / 2);
      ctx.fillStyle = "#f4ea2a";
      ctx.fill();

      const rectsPath = new Path2D();
      rectsPath.rect(x - r / 2, y - r / 5, r, (2 * r) / 5);
      rectsPath.arc(x - r / 2, y, r / 5, Math.PI / 2, (3 * Math.PI) / 2);
      rectsPath.arc(x + r / 2, y, r / 5, -Math.PI / 2, Math.PI / 2);
      ctx.clip(rectsPath);

      ctx.beginPath();
      ctx.arc(x + r / 3 + subX, y - r / 9 - subY, r / 6.5, 0, Math.PI * 2);
      ctx.fillStyle = "red";
      ctx.fill();

      ctx.beginPath();
      ctx.arc(x - r / 3 + subX, y - r / 9 - subY, r / 6.5, 0, Math.PI * 2);
      ctx.fillStyle = "red";
      ctx.fill();
    </script>
  </body>
</html>
